# _*_coding:utf-8 _*_
# @Time   :2020/6/28

import re
import random
import json
import requests
import logging
import os.path
import time
from core.myconfig import config
from core.sendemail import Sender
from core.myconfig import headers, Accept

logger = logging.getLogger()
logger.setLevel(logging.INFO)  # Log等级总开关
rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
log_path = os.path.dirname(os.getcwd()) + '/Logs/'
if not os.path.exists(log_path):
    os.makedirs(log_path)
log_name = log_path + rq + '.log'
logfile = log_name
fh = logging.FileHandler(logfile, mode='w')
fh.setLevel(logging.DEBUG)  # 输出到file的log等级的开关
# 第三步，定义handler的输出格式
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
fh.setFormatter(formatter)
# 第四步，将logger添加到handler里面
logger.addHandler(fh)
# 日志
# logger.debug('this is a logger debug message')
logger.info('Starting!')


# logger.warning('this is a logger warning message')
# logger.error('this is a logger error message')
# logger.critical('this is a logger critical message')


class SmartRobot:
    def __init__(self):
        self.sender = Sender()
        self.config = config  # 配置信息

        # 判断用户 登录信息(学号 身份证后六位) 是否正确
        self.loginurl = 'http://smart.hnsyu.net/xyt/wx/index/loginSubmit.do'
        # 判断是否已经报过平安
        self.mainurl = 'http://smart.hnsyu.net/xyt/wx/health/main.do'
        # 获取用户报平安的 token
        self.tokenurl = 'http://smart.hnsyu.net/xyt/wx/health/toApply.do'
        # 最后的报平安链接
        self.saveurl = 'http://smart.hnsyu.net/xyt/wx/health/saveApply.do'

    def getalluser(self, token=None, time='08:00'):
        """
        获取所有需要报修的用户
        """
        try:
            res = self.apigetuser(token, time)
            return json.loads(res)['data']
        except Exception as e:
            print(e)
            return None

    def doapply(self, session, tokeninfo, headers):
        """
        报平安函数
        :param userinfo: 单个用户信息
        :return:
        """
        res = SmartRobot.post(session=session,
                              url=self.saveurl,
                              data=tokeninfo,
                              header=headers)
        if json.loads(res.text)['msgText'] == '保存成功！':
            return True
        return False

    def filldata(self, userinfo):
        """
        数据填充
        """
        data = {
            "ttoken": userinfo["token"],
            "province": userinfo["province"],  # 省份
            "city": userinfo["city"],  # 城市
            "district": userinfo["district"],  # 地区
            "adcode": "",  # 城市编码
            "longitude": 0,  # 经度
            "latitude": 0,  # 纬度
            "sfqz": "否",  # 是否确证
            "sfys": "否",  # 是否疑似
            "sfzy": "否",  #
            "sfgl": "否",  # 是否隔离
            "status": 1,  # 状态  异常（温度异常，不良反应）状态是为2
            "sfgr": "否",  # 是否感染 # 是否确证？/疑似？/被隔离？
            "szdz": userinfo["province"] + " " + userinfo["city"] + " " + userinfo["district"],  # 所在地址
            "sjh": userinfo["sjh"],  # 手机号
            "lxrxm": userinfo["lxrxm"],  # 联系人姓名
            "lxrsjh": userinfo["lxrsjh"],  # 联系人手机号
            "sffr": "否",  # 是否发热 # 今日体温是否异常
            "sffy": "否",  # 是否反应
            "sfgr": "否",  # 是否感染
            "qzglsj": "",  # 确证隔离时间
            "qzgldd": "",  # 确证隔离地点
            "glyy": "",  # 隔离原因
            "mqzz": "",  # 目前症状
            "sffx": "否",  # 是否返校 # 是否有出行计划
            "qt": ""  # 其他健康情况
        }
        return data

    def login(self, session, userinfo, headers):
        username = userinfo['account']
        passwd = userinfo['password']
        logindata = {
            'username': username,
            'password': passwd
        }
        res = SmartRobot.post(session=session, url=self.loginurl, data=logindata, header=headers)
        if res.text == 'success':
            return True
        return False

    def getoken(self, session, headers):
        """
        获取用户报平安的 token
        """
        res = SmartRobot.post(session=session, url=self.tokenurl, header=headers)
        ttoken = re.search('ttoken" value="[A-Za-z0-9\-]+"', res.text)
        if ttoken is not None:
            print('ttoken origin:{}'.format(ttoken))
            ttoken = ttoken[0].replace('ttoken" value="', '').strip('"')
            return ttoken
        return None

    def isfinish(self, session, headers):
        res = SmartRobot.post(url=self.mainurl, session=session, header=headers)
        text = re.search('"normal-sm-tip green-warn fn-ml10">[\u4e00-\u9fa5]+', res.text)
        if text is not None:
            return True
        return False

    def randomheader(self):
        headers["User-Agent"] = random.choice(Accept)
        return headers

    def forone(self, userinfo):
        """
        判断该用户 登录信息是否正确
        """
        session = requests.session()
        headers = self.randomheader()
        # 判断用户 登录信息(学号 身份证后六位) 是否正确
        logres = self.login(session, userinfo, headers)

        # 用户的 账号密码正确
        if logres:
            # logger.info('login success:{}'.format(logres))
            # 判断是否已经报过平安
            checzkres = self.isfinish(session=session, headers=headers)
            # logger.info('user is finished:{}'.format(checzkres))
            # 如果该用户尚未报平安
            if not checzkres:
                # 获取用户的 token
                token = self.getoken(session, headers)
                # 成功获取 token
                if token is not None:
                    userinfo['token'] = token
                    data = self.filldata(userinfo=userinfo)
                    # 报平安
                    applyres = self.doapply(session, data, headers)
                    # 如果报平安成功
                    if applyres:
                        logger.info('finish:{}'.format(userinfo['account']))
                        return True
                    return False
                # 获取用户 token 失败
                return False
            # 说明已经报过平安了
            return None
        # 说明用户账号、密码不正确
        # logger.info('login fail ! ')
        return False

    def main(self, time):
        """
        主执行函数，方便后期扩展为进程类
        :return:
        """
        successmail = []
        successusers = []
        erroremail = []
        errorlist = []
        finalerror = []
        trytimes = 2  # 只尝试两次获取需要报平安的用户的信息
        while True:
            # 给用户报平安
            alluser = self.getalluser(token=config['token'], time=time)
            if alluser is not None:
                for user in alluser:
                    # 给用户 使用脚本报平安
                    foroneres = self.forone(user)
                    if foroneres is not None:
                        if foroneres:
                            successmail.append(user['email'])
                            successusers.append(user['username'])
                        else:
                            errorlist.append(user)
                    else:  # 已经报过平安的就不用管了
                        pass
                # 两次报平安的机会
                # errorlist 包括第一次 获取token失败的用户和报平安最后一步失败的用户
                for user in errorlist:
                    forone = self.forone(user)
                    if forone is not None:
                        if forone:
                            successmail.append(user['email'])
                            successusers.append(user['username'])
                        else:
                            finalerror.append(user['username'])  # bug ,无限添加 ！
                            erroremail.append(user['email'])  # 如果第二次失败了就添加进去
                    else:  # 已经报过平安的就不用管了
                        pass
                # 给用户发邮件
                logger.info('successusers:{} type:{}'.format(successusers, type(successusers)))
                logger.info('successusers:{} type:{}'.format(successmail, type(successmail)))
                logger.info('fail users:{}'.format(finalerror))
                self.sendfinishinfo(successusers, config['token'])
                self.sendsuccessemail(successmail)
                self.senderroremail(erroremail)
                break  # 如果没异常就退出
            else:
                if trytimes > 0:
                    trytimes -= 1
                    logger.info('get user info error!')
                    continue  # 有异常就再操作一次,共计两次
                else:
                    break

    def sendsuccessemail(self, emails):
        """
        给用户发送成功邮件
        """
        self.sender.getemail(emails, True)

    def senderroremail(self, emails):
        """
        给用户发送失败邮件
        """
        self.sender.getemail(emails, False)

    def apigetuser(self, token, time):
        """
        用来获得需要报平安的用户
        """
        data = {
            'time': time
        }
        headers = {
            "Content-Type": "application/json;charset=UTF-8",
            "Authorization": "token {}".format(token)
        }
        res = requests.post('http://127.0.0.1:80/finduserbytime', json=data, headers=headers)
        print(res.text)
        return res.text

    def sendfinishinfo(self, users, token):
        """
        用来 使成功的用户天数减一
        """
        data = {
            'users': users
        }
        headers = {
            "Content-Type": "application/json;charset=UTF-8",
            "Authorization": "token {}".format(token)
        }
        res = requests.post('https://127.0.0.1:80/finishusers', json=data, headers=headers)
        return res.text

    @staticmethod
    def post(session, url, header, data=None):
        try:
            return session.post(url=url, params=data, headers=header)
        except:
            logger.info('post error! ')
            pass

    @staticmethod
    def get(session, url, header):
        return session.get(url=url, headers=headers)


if __name__ == '__main__':
    self = SmartRobot()
    # self.main('08:00')

    userinfo = {'province': '山东省', 'city': '聊城', 'district': '冠县', 'sjh': '17873954278', 'lxrxm': '陈文昌', 'lxrsjh': '17669675667', 'account': 1841302004, 'password': '1841302004', 'email': '2842936326@qq.com', 'start': 1, 'days': 3, 'username': 'propose'}
    self.forone(userinfo)
    # self.getalluser('40e0bb9890b72c3e5a89e7a992502a5b4c853e42', '08:00')
